var CONFIG = require('../../../../common/config');
var CODE = require('../../../../common/code');
var CommonUtil = require('../../../../common/util/CommonUtil');
var documentUtil = require('./documentUtil');
var async = require('async');
var YjxTradeOrderModel = require('../../../../common/yjxMysql/mapping/YjxTradeOrderModel');
var YjxPaymentHisModel = require('../../../../common/yjxMysql/mapping/YjxPaymentHisModel');
var YjxTradeStateHisModel = require('../../../../common/yjxMysql/mapping/YjxTradeStateHisModel');
var YjxUniUserDocModel = require('../../../../common/yjxMysql/mapping/YjxUniUserDocModel');
var YjxCouponModel = require('../../../../common/yjxMysql/mapping/YjxCouponModel');
var YjxDesignUserDocModel = require('../../../../common/yjxMysql/mapping/YjxDesignUserDocModel');
var YjxVideoUserDocModel = require('../../../../common/yjxMysql/mapping/YjxVideoUserDocModel');
var YjxPriceModel = require('../../../../common/yjxMysql/mapping/YjxPriceModel');
var YjxTradeOdrDtlWmModel = require('../../../../common/yjxMysql/mapping/YjxTradeOdrDtlWmModel');
var YjxTradeOdrDtlVipModel = require('../../../../common/yjxMysql/mapping/YjxTradeOdrDtlVipModel');
var YjxTradeOdrDtlPtsModel = require('../../../../common/yjxMysql/mapping/YjxTradeOdrDtlPtsModel');
var YjxUserPointsHisModel = require('../../../../common/yjxMysql/mapping/YjxUserPointsHisModel');
var YjxUniItemsModel = require('../../../../common/yjxMysql/mapping/YjxUniItemsModel');
var YjxMemberModel = require('../../../../common/yjxMysql/mapping/YjxMemberModel');
var ItbUserModel = require('../../../../common/mysql/mapping/ItbUserModel');
var request = require('request');
var xml2js = require('xml2js');
var crypto = require('crypto');
var superagent = require('superagent');
var path = require('path');


var optionsForAliPay = {
    appId: '2018041602565700',
    rsaPrivate: path.resolve(__dirname, '../../ext/alipay_yjsc_private_key.pem'),
    rsaPublic: path.resolve(__dirname, '../../ext/alipay_yjsc_ali_public_key.pem'),
    sandbox: false,
    signType: 'RSA2',
    notifyUrl: 'https://paycb.itbour.com:818/yjxPay/chkAlipayNotify'   // 正式支付回调
};
if(CONFIG.DEBUG) {
    // 测试环境 支付回调
    optionsForAliPay.notifyUrl = 'http://test.itbour.com:3006/yjxPay/chkAlipayNotify';
}
/*
* 切记:
* 1. 官方未提供 nodejs sdk, 此处使用 alipay-node-sdk 是自行签名操作, 使用签名时一定使用第二种生成方式, 官方提供工具有问题
* 2. 阿里公钥是 txt 形式, 转 pem 格式, 添加 begin 头 end 尾, 每64字符换行,
* */
var Alipay = require('alipay-node-sdk');
var yjxAlipayClient = new Alipay(optionsForAliPay);


//==========================================================================
// 网站和APP用 (对应开放平台) <一键生成>
// var YJX_PAY_WX_INFO = {
//     APPID: 'wxb6504bf6ff28cb10',// APP的APPID(微信开放平台审核通过的应用APPID)
//     MCH_ID: '1419473302',// 商户ID
//     KEY: 'Wefub8730xfyFekodbfgoFQmmnOwEREp',// ［key为在微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置］
// };

// 网站和APP用 (对应开放平台) <一键秀>
var YJX_PAY_WX_INFO = {
    APPID: 'wx5022d3c8ad81e74f',// APP的APPID(微信开放平台审核通过的应用APPID)
    MCH_ID: '1492744852',// 商户ID
    KEY: 'Wefub8730xfyFekodbfgoFQmmnOwEYJX',// ［key为在微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置］
};

// H5用 (对应公众平台:一键生成创业板)
var YJX_PAY_WX_INFO_2 = {
    APPID: 'wx3d505dd750d82e65',// 公众号的APPID
    MCH_ID: '1427545102',// 商户ID
    KEY: 'Eefub3556xfyFekDEbfgoETmmnOw22Ep'// 在商户平台手动生成
};


/**
 * 一键秀 IAP 商品映射表
 * @key     商品价格, 单位: 分
 * @value   IAP 商品标识
 *
 * 注意: 尚未添加 iOS 商品
 */
var YJX_IAP_ITEMS_MAP = {
    // 去水印价格表
    wm : {
        '600'  : 'yjx_0000000002',   // 6块
        '1200' : 'yjx_0000000003',   // 12块
        '1800' : 'yjx_0000000004',   // 18块
        '2500' : 'yjx_0000000005',   // 25块
        '3000' : 'yjx_0000000006',   // 30块
        '9800' : 'yjx_0000000007',   // 98块
        '18800' : 'yjx_00000000013',   // 188块
        '32800' : 'yjx_00000000011',   // 328块
        '51800' : 'yjx_00000000012',   // 518块去水印
    },
    // vip 价格表
    vip : {
        '299800' : 'yjx_0000000008', // 2998 块
        '149800' : 'yjx_0000000009', // 1498 块
    },
    // 秀米充值价格表
    xm : {
        '6800' : 'yjx_0000000023', // 68 块
        '12800' : 'yjx_0000000020', // 128 块
        '41800' : 'yjx_0000000021', // 418 块
        '299800' : 'yjx_0000000022' // 2998块
    }
};

//==========================================================================
var orderUtil = (function () {

    function orderUtil() {
        //
    }

    //==========================================================================
    /**
     * 拼接参数字符串(eg: key1=value1&key2=value2…)
     * ◆ 参数名ASCII码从小到大排序（字典序）
     * ◆ 如果参数的值为空不参与签名
     * ◆ 参数名区分大小写
     * @param args: 字典对象
     * @returns {string}
     */
    orderUtil.toWxParamStr = function(args) {
        var keys = Object.keys(args);
        keys = keys.sort();
        var newArgs = {};
        keys.forEach(function (key) {
            if(args[key]!=null && (args[key]+'')!='') {// 过滤空值项
                //newArgs[key.toLowerCase()] = args[key];
                newArgs[key] = args[key];// 签名时候的参数不需要转换为小写的
            }
        });
        var str = '';
        for (var k in newArgs) {
            str += '&' + k + '=' + newArgs[k];
        }
        str = str.substr(1);
        return str;
    };

    //==========================================================================
    /**
     * 计算[微信支付]签名
     * @param key: 密钥
     * @param param: 参数
     * @returns {string}
     */
    orderUtil.calcWxPaySign = function(key, param) {
        var paramObj = param||{};
        var paramStr = orderUtil.toWxParamStr(paramObj);

        key = key || YJX_PAY_WX_INFO.KEY;

        paramStr = paramStr + '&key='+key;
        console.log("CalcParam: "+paramStr);
        var sign = crypto.createHash('md5').update(paramStr,'utf8').digest('hex');
        sign = sign.toUpperCase();
        console.log("CalcSign: "+sign);
        return sign;
    };

    //==========================================================================
    /**
     * 调用微信支付[统一下单]API
     * 参数 key: 密钥
     * 参数 formData: XML格式参数
     */
    orderUtil.reqWxApi_payUniOrd = function(key, formData, cb) {
        var url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        request({url:url,method:'POST',body: formData},function(err,response,retBody){
            if(!err && response.statusCode == 200){
                console.log(retBody);

                var parser = new xml2js.Parser({ trim:true, explicitArray:false, explicitRoot:false });
                parser.parseString((retBody||'').toString("utf-8"), function(parseErr, parseRet){
                    if(parseErr) {
                        console.log('orderUtil.js [reqWxApi] parser xml Err: '+parseErr);
                        return cb(parseErr, null);
                    }

                    // 验证返回值签名
                    var retSign = parseRet.sign||'';
                    if(parseRet.sign){
                        delete parseRet.sign;
                    }
                    var calSign = orderUtil.calcWxPaySign(key, parseRet);

                    console.log('retSign:[' + retSign + '] calSign:[' + calSign + ']');
                    if (!retSign || !calSign || retSign.toUpperCase() != calSign.toUpperCase()) {
                        return cb('[微信统一下单]返回数据非法', null);
                    }

                    // [return_code] 此字段是通信标识，非交易标识，交易是否成功需要查看result_code来判断
                    if((parseRet.return_code||'')=='SUCCESS') {

                        // 以下字段在return_code 和result_code都为SUCCESS的时候有返回:
                        // [trade_type]: 交易类型(调用接口提交的交易类型，取值如下：JSAPI，NATIVE，APP)
                        // [prepay_id]: 预支付交易会话标识,(微信生成的预支付回话标识，用于后续接口调用中使用，该值有效期为2小时)
                        if((parseRet.result_code||'')=='SUCCESS') {
                            parseRet.sign = retSign;
                            return cb(null, parseRet);
                        } else {
                            return cb(parseRet.err_code||'[微信统一下单]交易失败', null);
                        }

                    } else {
                        return cb(parseRet.return_msg||'[微信统一下单]通信失败', null);
                    }
                });
            } else {
                return cb(err, null);
            }
        });
    };

    //==========================================================================
    /**
     * 参数 device: 6 字段为 一键秀 相关标记
     *             600 一键秀 网页端/PC
     *             610 一键秀 Android 端
     *             620 一键秀 iOS 端
     *             630 一键秀 APP端 嵌入H5
     *             640 一键秀 微信端 嵌入H5
     *             650 一键秀 小程序端
     * 4:pc, 5:ios ,6:android, 7:微信嵌入h5, 8:小程序, 9:app嵌入h5
     */
    orderUtil.DEVICE_ID_MAP ={"600":4, "610":6, "620":5, "630":9, "640":7, "650":8};
    orderUtil.DEVICE_P01_FLAG_MAP ={
        "10":CONFIG.ORDER_TYPE_ORDER// 1
        //"20":CONFIG.ORDER_TYPE_INVOICE,
        //"30":CONFIG.ORDER_TYPE_TEMPLATE,
        //"40":CONFIG.ORDER_TYPE_VIP,
        //"50":CONFIG.ORDER_TYPE_SECKILL
    };
    /**
     * 创建各种类型的订单编号
     * 参数 device: 请求来源
     * 参数 orderType: [保留参数,暂时可设null] 商品订单:10  发票订单:20  模版订单:30  虚拟商品订单:40  秒杀订单:50
     * 返回值: 订单编号
     */
    orderUtil.createOrderNo = function(device, orderType){
        var cur = CommonUtil.genCurYearDayTimeStr();
        var p00 = orderUtil.DEVICE_ID_MAP[device] || 0; // 标志
        //var p01 = orderUtil.DEVICE_P01_FLAG_MAP[orderType] ||0; // 订单类型
        var p01 = 1; // TODO 暂时默认为1
        var p0 = p00+""+p01;
        var p1 = cur.substr(8); // 分秒
        var p2 = CommonUtil.randomNumStr(3); // 3位随机数
        var p3 = cur.substr(0,8);// 年月日时
        p3 = CommonUtil.yearDayTimeStrtoAlphabet(p3); // 4位26进制字符串
        var ret = CommonUtil.mix(p0+p1+p2, p3);
        return ret;
    };

    //==========================================================================
    /**
     * 根据订单状态更新优惠券状态
     * @param tradeObjId: 订单id
     * @param tradeType: [待定] 10商品订单 20发票订单 30模版订单 40虚拟商品
     * @param tradeState: 订单状态
     * @param userId:     更新者
     * @param callback
     */
    orderUtil.updConponState = function(tradeObjId, tradeType, tradeState, userId, callback) {
        if(tradeState==CONFIG.YJX_ORDER_STATE.PAID) {
            // 支付成功
            (new YjxCouponModel).updStateByPaidOrder(tradeObjId, function(err, ret){
                return callback(err, ret);
            });
        } else if(tradeState==CONFIG.YJX_ORDER_STATE.CANCELLED) {
            // 订单取消,解绑优惠券
            (new YjxCouponModel).unbindCanceledOrderOnly(tradeObjId, function(err, ret){
                return callback(err, ret);
            });
        } else {
            return callback(null, null);
        }
    };

    //==========================================================================
    /**
     * 更新订单状态
     * @param tradeObjId: 订单id
     * @param tradeType:  [待定] 10商品订单 20发票订单 30模版订单 40虚拟商品 50秒杀订单
     * @param tradeState: 订单状态
     * @param totalFee:   订单金额
     * @param userId:     更新者
     * @param callback
     */
    orderUtil.updOrderState = function(tradeObjId, tradeType, tradeState, totalFee, userId, callback, total_cost_pts){

        tradeType = Number(tradeType||'0')||0;

        var updEnt = new YjxTradeOrderModel({
            order_id: tradeObjId||0,
            state: tradeState||0,
            update_by: userId||''
        });
        if(tradeState==CONFIG.YJX_ORDER_STATE.FINISH) {
            // 订单完成: 需同步设置完成时间
            updEnt.arrUpdSysDtFieldNm=['finish_time'];
        }
        var hisDesc = '[YjxTradeOrderModel] Upd to [state:'+tradeState+']';

        updEnt.updateToDB_SysDt(function(updErr){
            if(updErr){
                console.log("orderUtil.js [updateToDB_SysDt] Upd State Err: "+updErr);
                hisDesc += ' NG';
            } else {
                hisDesc += ' OK';
            }

            // 添加状态变更纪录
            var hisEnt = new YjxTradeStateHisModel({
                trade_type: tradeType||0,
                trade_obj_id: tradeObjId||0,
                state: tradeState,
                total_fee: totalFee||0,
                total_cost_pts: total_cost_pts||0,
                desc: hisDesc,
                user_id: userId||0,
                update_by: userId||'未知'
            });
            hisEnt.saveToDB(function(insErr, newHisId){
                if(insErr){
                    console.log("orderUtil.js [updOrderState] Ins StateHis Err: "+insErr);
                    return callback(insErr,null);
                }

                // 更新绑定的优惠券状态
                orderUtil.updConponState(tradeObjId, tradeType, tradeState, userId, function(updErr, updRet){
                    return callback(null, null);
                });
            });
        });
    };

    //==========================================================================
    // 微信支付统一订单接口
    orderUtil.getUnifiedOrderPayParam_WX=function(device, userId, orderType, orderId, callback){
        var H5PayFlg = false;
        if(device == '630') {// 微信内嵌H5支付
            H5PayFlg = true;
        }

        // Parameter
        var timeStamp = Math.floor(Date.now()/1000)+"";// 时间戳
        var openid = "";// TODO

        var trade_type = "APP";// 交易类型(必填): APP/JSAPI/NATIVE(会返回code_url)
        var appid = YJX_PAY_WX_INFO.APPID;// 应用ID(必填)
        var mch_id = YJX_PAY_WX_INFO.MCH_ID;// 商户号(必填)
        var key = YJX_PAY_WX_INFO.KEY;
        // 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数
        // 支付成功后微信服务器通过POST请求通知这个地址
        var notify_url = 'https://paycb.itbour.com:818/yjxPay/chkWxPayNotify';// TODO
        if(CONFIG.DEBUG==1) {
            notify_url = 'http://paycb.itbour.com/yjxPay/chkWxPayNotify';
        }else if(CONFIG.DEBUG==2){
            notify_url = 'http://test.itbour.com:3006/yjxPay/chkWxPayNotify';
        }

        if(H5PayFlg) {// 内嵌H5支付
            trade_type = 'JSAPI';
            appid = YJX_PAY_WX_INFO_2.APPID;
            mch_id = YJX_PAY_WX_INFO_2.MCH_ID;
            key = YJX_PAY_WX_INFO_2.KEY;
            notify_url = 'https://paycb.itbour.com:818/yjxPay/chkWxPayNotify2';// TODO
            if(CONFIG.DEBUG) {
                notify_url = 'http://paycb.itbour.com/yjxPay/chkWxPayNotify2';
            }else if(CONFIG.DEBUG==2){
                notify_url = 'http://test.itbour.com:3006/yjxPay/chkWxPayNotify2';
            }
        }

        // 附加数据: 暂定纪录userId,tradeObjId,type
        var attach = JSON.stringify({
            uid: userId||0, id: orderId||0, type: orderType||0
        });
        var body = "示界港微信支付订单";// 商品或支付单简要描述 TODO

        var nonce_str = CommonUtil.genNonceStr(32);// 随机字符串,不长于32位(必填)

        var ip = "127.0.0.1";// 终端IP(必填) TODO

        var paramForSign = {
            appid: appid,
            attach: attach,
            body: body,
            mch_id: mch_id,
            nonce_str: nonce_str,
            notify_url: notify_url,
            openid: openid,
            out_trade_no: '',// 商户订单号(必填)
            spbill_create_ip: ip,
            total_fee: 0,// 总金额(必填)
            trade_type: trade_type
        };

        // 获取订单信息
        //if(type == 10 || type == 20 || type == 40 || type == 50) {
            var orderEnt = null;
            //if(type == 10 || type == 40 || type == 50) {// 商品订单
                orderEnt = new YjxTradeOrderModel({
                    order_id: orderId,
                    del_flg: 0
                });
            //} else if(type == 20){// 发票订单
            //    orderEnt = new ItbInvoiceModel({
            //        inv_id: tradeObjId,
            //        del_flg: 0
            //    });
            //}
            orderEnt.findFromDB(function(error, data){
                if(data && data.length>0){

                    var curState = Number(data[0].state || '0');
                    if(curState == 11) {
                        return callback('该订单已支付成功，无需重复支付', null);
                    } else if(curState == 50) {
                        return callback('该订单因超时已取消，请重新下单', null);
                    }

                    paramForSign.out_trade_no = '';
                    //if(type == 10 || type == 40 || type == 50) {
                        paramForSign.out_trade_no = data[0].order_no;
                        paramForSign.total_fee = data[0].total_fee || 0;// 商品订单总金额
                    //} else if(type == 20) {
                    //    paramForSign.out_trade_no = data[0].inv_no;
                    //    paramForSign.total_fee = data[0].mail_fee || 0;// 发票只算邮费
                    //}

                    // 先统一更新为支付失败
                    orderUtil.updOrderState(orderId, orderType, CONFIG.YJX_ORDER_STATE.FAILED, paramForSign.total_fee, userId,
                        function(updErr, updRet){
                            if (updErr) {
                                console.log("orderUtil.js [getUnifiedOrderPayParam_WX] Upd State(12) Err: " + updErr);
                                return callback(updErr, null);
                            }

                            // 开始支付
                            if(paramForSign.total_fee == 0) {// 免费不用支付
                                // 添加支付历史纪录
                                var hisEnt = new YjxPaymentHisModel({
                                    trade_type: orderType||0,
                                    trade_obj_id: orderId||0,
                                    trade_obj_no: paramForSign.out_trade_no||0,
                                    state: CONFIG.YJX_ORDER_STATE.PAID,
                                    pay_platform: 0,// 无
                                    desc: 'SUCCESS',
                                    update_by: userId||0
                                });
                                hisEnt.saveToDB(function(insErr, newHisId) {
                                    if(insErr) {
                                        console.log("orderUtil.js [getUnifiedOrderPayParam_WX] Ins PayHis Err: " + insErr);
                                    }

                                    orderUtil.updOrderState(orderId, orderType, CONFIG.YJX_ORDER_STATE.PAID, 0, userId, function(updErr2, updRet2){
                                        if(updErr2) {
                                            return callback(updErr2, null);
                                        }

                                        console.log("orderUtil.js [getUnifiedOrderPayParam_WX] Upd fee=0 Order ");

                                        // 支付成功后续处理 added by xc 2018-03-27
                                        orderUtil.procVipAndPtsOrder({userId:userId, orderId:orderId, updOdrFlg:1}, function(procErr,procRet){
                                            return callback(procErr, procRet);
                                        });
                                    });
                                });

                            } else {// 需要支付
                                // 调用微信下单接口
                                var formData  = "<xml>";
                                formData  += "<appid>"+paramForSign.appid+"</appid>";  // 应用ID(必填)
                                formData  += "<attach>"+paramForSign.attach+"</attach>"; // 附加数据
                                formData  += "<body>"+paramForSign.body+"</body>";// 商品或支付单简要描述
                                formData  += "<mch_id>"+paramForSign.mch_id+"</mch_id>";// 商户号(必填)
                                formData  += "<nonce_str>"+paramForSign.nonce_str+"</nonce_str>";// 随机字符串,不长于32位(必填)
                                formData  += "<notify_url>"+paramForSign.notify_url+"</notify_url>";// 通知地址(必填)
                                formData  += "<openid>"+paramForSign.openid+"</openid>";
                                formData  += "<out_trade_no>"+paramForSign.out_trade_no+"</out_trade_no>";// 商户订单号(必填)
                                formData  += "<spbill_create_ip>"+paramForSign.spbill_create_ip+"</spbill_create_ip>";// 终端IP(必填)
                                formData  += "<total_fee>"+paramForSign.total_fee+"</total_fee>";// 总金额(必填)
                                formData  += "<trade_type>"+paramForSign.trade_type+"</trade_type>";// 交易类型(必填)
                                formData  += "<sign>"+orderUtil.calcWxPaySign(key, paramForSign)+"</sign>";
                                formData  += "</xml>";

                                orderUtil.reqWxApi_payUniOrd(key, formData, function(retErr, retInfo){
                                    if(retErr) {
                                        return callback(retErr, null);
                                    }

                                    if(retInfo && retInfo.prepay_id) {
                                        // 统一下单接口返回正常的prepay_id, 再按签名规范重新生成签名后, 将数据传输给APP。
                                        // 参与签名的字段名为appId, partnerId, prepayId, nonceStr, timeStamp, package。
                                        // 注意: package的值格式为Sign=WXPay

                                        //var paramForSign2 = {
                                        //    appId: appid,
                                        //    partnerId: mch_id,
                                        //    prepayId: retInfo.prepay_id,
                                        //    nonceStr: payUtil.genNonceStr(32),
                                        //    timeStamp: Math.floor(Date.now()/1000)+"",
                                        //    package: "Sign=WXPay"
                                        //};

                                        var paramForSign2 = {};
                                        var ns = CommonUtil.genNonceStr(32);
                                        var ts = Math.floor(Date.now()/1000)+"";

                                        if(H5PayFlg) {// 内嵌H5支付
                                            paramForSign2 = {// 参数名区分大小写 !!!???
                                                appId: appid,
                                                timeStamp: ts,
                                                nonceStr: ns,
                                                package: "prepay_id="+retInfo.prepay_id,
                                                signType: 'MD5'
                                            };

                                        } else {// APP,网页支付
                                            paramForSign2 = {// 巨坑: 参数名需要小写 !!!???
                                                appid: appid,
                                                partnerid: mch_id,
                                                prepayid: retInfo.prepay_id,
                                                noncestr: ns,
                                                timestamp: ts,
                                                package: "Sign=WXPay"
                                            };
                                        }

                                        var sign2 = orderUtil.calcWxPaySign(key, paramForSign2);

                                        return callback(null, {
                                            prepayId:retInfo.prepay_id,
                                            nonceStr:ns,
                                            timeStamp:ts,
                                            sign:sign2
                                        });

                                    } else {
                                        return callback('预支付交易会话标识获取失败', null);
                                    }
                                });
                            }
                        }
                    );

                }else{
                    return callback('无效订单', null);
                }
            }, 0, 1);

        //} else {
        //    return callback('无效订单分类', null);
        //}
    };

    // 微信支付统一下单 (网页扫码支付用)
    orderUtil.getUnifiedOrderPayParam_Web = function(device, userId, orderType, tradeObjId, callback) {

        // Parameter
        var timeStamp = Math.floor(Date.now()/1000)+"";// 时间戳

        // 附加数据: 暂定纪录userId,tradeObjId,type
        var attach = JSON.stringify({
            uid: userId||0, id: tradeObjId||0, type: orderType||0
        });

        // 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数
        // 支付成功后微信服务器通过POST请求通知这个地址
        var notify_url = 'https://paycb.itbour.com:818/yjxPay/chkWxPayNotify';// TODO
        if(CONFIG.DEBUG==1) {
            notify_url = 'http://paycb.itbour.com/yjxPay/chkWxPayNotify';
        }else if(CONFIG.DEBUG==2){
            notify_url = 'http://test.itbour.com:3006/yjxPay/chkWxPayNotify';
        }

        var key = YJX_PAY_WX_INFO.KEY;

        var paramForSign = {
            appid:              YJX_PAY_WX_INFO.APPID,// 应用ID(必填)
            attach:             attach,
            body:               "示界港微信支付订单",// 商品或支付单简要描述 TODO
            device_info:        'WEB',
            mch_id:             YJX_PAY_WX_INFO.MCH_ID,// 商户号(必填)
            nonce_str:          CommonUtil.genNonceStr(32),// 随机字符串,不长于32位(必填)
            notify_url:         notify_url,
            out_trade_no:       '',// 商户订单号(必填)
            spbill_create_ip:   "127.0.0.1",// 终端IP(必填) TODO
            total_fee:          0,// 总金额(必填)
            trade_type:         'NATIVE'// 交易类型(必填): APP/JSAPI/NATIVE(会返回code_url)
        };

        // 获取订单信息
        //if(type == 10 || type == 20 || type == 40 || type == 50) {
            var orderEnt = null;

            //if(type == 10 || type == 40 || type == 50) {// 商品订单
                orderEnt = new YjxTradeOrderModel({
                    order_id: tradeObjId,
                    del_flg: 0
                });
            //} else if(type == 20){// 发票订单
            //    orderEnt = new ItbInvoiceModel({
            //        inv_id: tradeObjId,
            //        del_flg: 0
            //    });
            //}
            orderEnt.findFromDB(function(error, data){
                if(data && data.length>0){

                    var curState = Number(data[0].state || '0');
                    if(curState == 11) {
                        return callback('该订单已支付成功，无需重复支付', null);
                    } else if(curState == 50) {
                        return callback('该订单因超时已取消，请重新下单', null);
                    }

                    paramForSign.out_trade_no = '';
                    //if(type == 10 || type == 40 || type == 50) {
                        paramForSign.out_trade_no = data[0].order_no;
                        paramForSign.total_fee = data[0].total_fee || 0;// 商品订单总金额
                    //} else if(type == 20) {
                    //    paramForSign.out_trade_no = data[0].inv_no;
                    //    paramForSign.total_fee = data[0].mail_fee || 0;// 发票只算邮费
                    //}

                    // 先统一更新为[支付失败]
                    orderUtil.updOrderState(tradeObjId, orderType, CONFIG.YJX_ORDER_STATE.FAILED, paramForSign.total_fee, userId,
                        function(updErr, updRet){
                            if (updErr) {
                                console.log("orderUtil.js [getUnifiedOrderPayParam_Web] Upd State(12) Err: " + updErr);
                                return callback(updErr, null);
                            }

                            // 开始支付
                            if(paramForSign.total_fee == 0) {// 免费不用支付
                                // 添加支付历史纪录
                                var insEnt = new YjxPaymentHisModel({
                                    trade_type: orderType||0,
                                    trade_obj_id: tradeObjId||0,
                                    trade_obj_no: paramForSign.out_trade_no||0,
                                    state: CONFIG.YJX_ORDER_STATE.PAID,
                                    pay_platform: 0,// 无
                                    desc: 'SUCCESS',
                                    update_by: userId||0
                                });
                                insEnt.saveToDB(function(insErr, newHisId) {
                                    if (insErr) {
                                        console.log("orderUtil.js [getUnifiedOrderPayParam_Web] Ins PayHis Err: " + insErr);
                                    }
                                    // 更新为[支付成功]
                                    orderUtil.updOrderState(tradeObjId, orderType, CONFIG.YJX_ORDER_STATE.PAID, 0, userId, function(updErr2, updRet2){
                                        if(updErr2) {
                                            return callback(updErr2, null);
                                        }

                                        console.log("orderUtil.js [getUnifiedOrderPayParam_Web] Upd fee=0 Order ");

                                        // 支付成功后续处理 added by xc 2018-03-27
                                        orderUtil.procVipAndPtsOrder({userId:userId, orderId:tradeObjId, updOdrFlg:1}, function(procErr,procRet){
                                            return callback(procErr, procRet);
                                        });
                                    });
                                });

                            } else {// 需要支付
                                // 调用微信下单接口
                                var formData  = "<xml>";
                                formData  += "<appid>"+paramForSign.appid+"</appid>";  // 应用ID(必填)
                                formData  += "<attach>"+paramForSign.attach+"</attach>"; // 附加数据
                                formData  += "<body>"+paramForSign.body+"</body>";// 商品或支付单简要描述
                                formData  += "<device_info>"+paramForSign.device_info+"</device_info>";
                                formData  += "<mch_id>"+paramForSign.mch_id+"</mch_id>";// 商户号(必填)
                                formData  += "<nonce_str>"+paramForSign.nonce_str+"</nonce_str>";// 随机字符串,不长于32位(必填)
                                formData  += "<notify_url>"+paramForSign.notify_url+"</notify_url>";// 通知地址(必填)
                                //formData  += "<openid>"+paramForSign.openid+"</openid>";
                                formData  += "<out_trade_no>"+paramForSign.out_trade_no+"</out_trade_no>";// 商户订单号(必填)
                                formData  += "<spbill_create_ip>"+paramForSign.spbill_create_ip+"</spbill_create_ip>";// 终端IP(必填)
                                formData  += "<total_fee>"+paramForSign.total_fee+"</total_fee>";// 总金额(必填)
                                formData  += "<trade_type>"+paramForSign.trade_type+"</trade_type>";// 交易类型(必填)
                                formData  += "<sign>"+orderUtil.calcWxPaySign(key, paramForSign)+"</sign>";
                                formData  += "</xml>";

                                orderUtil.reqWxApi_payUniOrd(key, formData, function(retErr, retInfo){
                                    if(retErr) {
                                        return callback(retErr, null);
                                    }

                                    if(retInfo && retInfo.prepay_id && retInfo.code_url) {
                                        return callback(null, {
                                            prepayId:retInfo.prepay_id||'',// 预支付交易会话标识
                                            codeUrl:retInfo.code_url||''// 二维码链接
                                        });

                                    } else {
                                        return callback('[微信支付二维码]获取失败', null);
                                    }
                                });
                            }
                        }
                    );

                }else{
                    return callback(error, null);
                }
            }, 0, 1);

        //} else {
        //    return callback('无效订单分类', null);
        //}
    };

    //==========================================================================
    /**
     * 获取订单支付参数
     * @author xc
     * @date 2017-11-20
     *
     * 参数 device: 6 字段为 一键秀 相关标记
     *             600 一键秀网页端
     *             610 一键秀 android 端
     *             620 一键秀 iOS 端
     *             630 一键秀 嵌入网页端
     *             640 一键秀微信端
     *             650 一键秀小程序端
     * 参数 userId: 用户唯一标识
     * 参数 orderType: [待定]
     * 参数 orderId: 用户订单唯一标识
     * 参数 paymentPlatform: [预留]支付平台类型
     *
     * 返回值:
     * {
            "success" : 1,                  // 0 标识请求失败, 1 标识请求成功
            "msg" : "成功",                 // 如请求失败, 则为失败原因
            "data" : {

                "orderId" : 3546,
                "orderNo" : "QWERTYUIO",
                "orderFee" : 989000,        // 订单支付金额, 单位: 分
                "paymentPlatform" : 10,     // 支付平台, 待定
                "wechat" : {               // 微信支付相关参数如下
                    "partnerId" : "10000100",
                    "prepayId": "1101000000140415649af9fc314aa427",
                    "package" : "Sign=WXPay",
                    "nonceStr": "a462b76e7436e98e0ed6e13c64b4fd1c",
                    "timeStamp": "1397527777",
                    "sign": "582282D72DD2B03AD892830965F428CB16E7A256",
                },
                "alipay" : {
                    "body":"对一笔交易的具体描述信息。如果是多种商品，请将商品描述字符串累加传给body。",
                    "subject":"大乐透",
                    "out_trade_no":"70501111111S001111119",
                    "timeout_express":"90m",
                    "total_amount":"一共花费了10元",
                    "product_code":"QUICK_MSECURITY_PAY",
                    "tips":"测试一笔支付",
                },
                "IAP" : {
                    "productIdentifier" : "00000001"
                }
            }
        }
     */
    orderUtil.getUnifiedOrderPayParam=function(device, userId, orderType, orderId, paymentPlatform, callback){

        var totalTasks = [];
        // 1. 查询订单信息
        totalTasks.push(function (callback) {
            var orderEnt = new YjxTradeOrderModel({
                order_id: orderId,
                user_id: userId,
                del_flg: 0
            });
            orderEnt.findFromDB(function(error, orders){
                if(error || !orders || orders.length <=0) {
                    return callback(error || '该订单不存在或非本账户订单', null);
                }
                var data = {};
                data.orderInfo = orders[0];
                data.retData = {
                    orderId: data.orderInfo.order_id,
                    orderNo: data.orderInfo.order_no,
                    orderFee: data.orderInfo.total_fee||0,
                    paymentPlatform: data.orderInfo.pay_platform||0
                };
                return callback(error, data);
            });
        });
        // 2, 订单检查
        totalTasks.push(function (data, callback) {
            data.orderInfo.state = Number(data.orderInfo.state);
            if(data.orderInfo.state === 11 ||
                data.orderInfo.state === 40) {
                return callback('该订单已支付无需重新支付', null);
            }
            return callback(null,data);
        });
        // 3. 作品检查
        totalTasks.push(function (data, callback) {
            // 只有去水印订单才检查
            if(!(data.orderInfo.odr_dtl_type_tag & 2)) {
                return callback(null, data);
            }
            //
            var entity = new YjxTradeOdrDtlWmModel();
            entity.getOrderUniDocPayState(data.orderInfo.order_id, function (error, uniDocs) {
                if(error || !uniDocs || uniDocs.length<=0) {
                    return callback(error || '该订单对应作品不存在或已删除', data);
                }
                var uniDoc = uniDocs[0];
                if(!uniDoc.watermark){
                    return callback("该作品已去水印", data);
                }
                if(uniDoc.wm_paid){
                    return callback("该作品已支付", data);
                }
                return callback(error, data);
            });
        });
        // 4. 按需获取微信支付参数
        totalTasks.push(function (data, callback) {
            if(Number(data.orderInfo.pay_platform) !== CONFIG.YJX_PAYMENT_PLATFORM.WECHAT) {
                return callback(null, data);
            }
            // 网页支付
            if(Number(device) === 600) {
                // 网页支付
                orderUtil.getUnifiedOrderPayParam_Web(device, userId, orderType, orderId, function(err, ret){
                    data.retData.wechat = ret||{};
                    return callback(err, data);
                });
                return;
            }
            // app 支付
            orderUtil.getUnifiedOrderPayParam_WX(device, userId, orderType, orderId, function(err, ret){
                data.retData.wechat = ret||{};
                return callback(err, data);
            });

        });
        // 5. 按需获取支付宝支付参数
        totalTasks.push(function (data, callback) {
            if(data.orderInfo.pay_platform !== CONFIG.YJX_PAYMENT_PLATFORM.ALIPAY) {
                return callback(null, data);
            }
            var opt = {
                device : device,
                userId : userId,
                orderType : orderType,
                orderId : orderId
            };
            orderUtil.getUnifiedOrderPayParam_alipay(opt, function (err, ret) {
                data.retData.alipay = ret || {};
                return callback(null, data);
            });
        });
        // 6. 按需获取 IAP 支付参数
        totalTasks.push(function (data, callback) {
            orderUtil.getUnifiedOrderPayParam_IAP(device, userId, orderType, orderId, function(err, ret){
                data.retData.IAP = ret||{};
                return callback(err, data);
            });
        });

        async.waterfall(totalTasks, function (error, data) {
            if(error) {
                return callback(error, null);
            }
            return callback(error, data.retData);
        });
    };


    //==========================================================================
    /**
     * 获取订单支付状态
     * @author xc
     * @date 2017-11-21
     *
     * 参数 device: 6 字段为 一键秀 相关标记
     * 参数 userId: 用户唯一标识
     * 参数 orderId: 用户订单唯一标识
     *
     * 返回值:
     * {
            "data" : {
                "orderId" : 878,
                "orderNo" : "QWERTYUIO",
                "orderFee" : 890000,        // 订单金额, 单位: 分
                "orderState" : 12,          // 订单支付状态, 暂时约定 11支付失败, 12 支付成功
                "paymentPlatform" : 10,     // 订单支付方式, 同获取订单支付参数接口
                "thirdNo" : "qwrtyioodgh",  // 第三方平台支付订单号
            }
        }
     */
    orderUtil.getOrderState_v1_0 = function(device, userId, orderId, callback){
        (new YjxTradeOrderModel).getOrderInfoWithPayInfo(orderId, function(err, ret){
            if(err) {
                return callback(err, null);
            }
            if(ret && ret.length>0) {
                var odrInfo = ret[0];

                return callback(null, {
                    "orderId": orderId,
                    "orderNo": odrInfo.order_no||'',
                    "orderFee": odrInfo.total_fee||0,
                    "orderState": odrInfo.state||0,
                    "paymentPlatform": odrInfo.pay_platform||0,
                    "thirdNo": odrInfo.transaction_id||0
                });

            } else {
                return callback('未知订单', null);
            }
        });
    };

    /**
     * 获取 IAP 内购参数
     *
     * @author 王俊
     * @date 2017-11-20
     *
     * @param device    6 字段为 一键秀 相关标记
     *                  600 一键秀网页端
     *                  610 一键秀 android 端
     *                  620 一键秀 iOS 端
     *                  630 一键秀 嵌入网页端
     *                  640 一键秀微信端
     *                  650 一键秀小程序端
     * @param userId    用户唯一标识
     * @param orderType [待定]
     * @param orderId   用户订单唯一标识
     * @param callback
     *           {
     *               "productIdentifier" : "00000001"
     *           }
     *       }
     *   }
     */
    orderUtil.getUnifiedOrderPayParam_IAP = function (device, userId, orderType, orderId, callback) {
        (new YjxTradeOrderModel).getOrderInfoWithPayInfo(orderId, function(err, orders){
            if(err || !orders || orders.length <=0) {
                return callback(err || '该订单不存在或已失效', null);
            }
            var orderInfo = orders[0];
            // 2[去水印订单],4[秒杀订单],8[vip订单],16[充值订单], 32[待定]'
            var identifier = null;
            if(orderInfo.odr_dtl_type_tag & 2) {
                identifier = YJX_IAP_ITEMS_MAP.wm[orderInfo.total_fee];
            }
            if(orderInfo.odr_dtl_type_tag & 8) {
                identifier = YJX_IAP_ITEMS_MAP.vip[orderInfo.total_fee];
            }
            if(orderInfo.odr_dtl_type_tag & 16) {
                identifier = YJX_IAP_ITEMS_MAP.xm[orderInfo.total_fee];
            }
            // 测试环境, 若没有 iOS 商品, 则使用默认去水印的值
            if(CONFIG.DEBUG && !identifier) {
                identifier = YJX_IAP_ITEMS_MAP.wm["600"];
            }

            if(!identifier || identifier.length <= 0) {
                return callback('当前订单暂不支持 iOS 内购支付', null);
            }

            return callback(err, {productIdentifier : identifier});
        });
    };

    /**
     * 获取 支付宝支付参数
     *
     * @author 王俊
     * @date 2018-04-24
     *
     * @param {Object} options  请求参数
     * @param {Number} options.device    设备唯一标识
     * @param {Number} options.userId    用户唯一标识
     * @param {Number} options.orderType 订单类型
     * @param {Number} options.orderId   订单唯一标识
     * @param {Number} [options.subject]   订单唯一标识
     * @param {Number} [options.body]   订单唯一标识
     * @param {Number} [options.goodsType]   订单唯一标识
     * @param {Number} [options.timeout]   订单唯一标识
     * @param {Function} callback  回调
     *          err:    获取失败
     *          data:   支付参数
     */
    orderUtil.getUnifiedOrderPayParam_alipay = function (options, callback) {
        // todo
        var totalTasks = [];

        // 1. 获取支付参数
        totalTasks.push(function (callback) {
            (new YjxTradeOrderModel).getOrderInfoWithPayInfo(options.orderId, function(err, orders){
                if(err || !orders || orders.length <=0) {
                    return callback(err || '该订单不存在或已失效', null);
                }
                var data = {};
                data.orderInfo = orders[0];
                return callback(err, data);
            });
        });
        // 2. 异常状态处理, 订单已支付, 零元支付
        totalTasks.push(function (data, callback) {
            //  '总订单状态: 10待支付、11已支付、12支付失败、20制作/处理中、[30配送中]、40完成、50取消',
            var disableStates = [11, 20, 30, 40];
            if(disableStates.indexOf(data.orderInfo.state) >=0) {
                return callback('该订单已支付, 请勿重新支付', data);
            }
            return callback(null, data);
        });

        // 3. 先更新为失败
        totalTasks.push(function (data, callback) {
            // 先统一更新为支付失败
            orderUtil.updOrderState(options.orderId, options.orderType, CONFIG.YJX_ORDER_STATE.FAILED, data.orderInfo.total_fee, options.userId,
                function(updErr, updRet){
                    if (updErr) {
                        console.log("orderUtil.js [getUnifiedOrderPayParam_WX] Upd State(12) Err: " + updErr);
                    }
                    return callback(updErr, data);
                }
            );
        });
        // 4. 零元处理
        totalTasks.push(function (data, callback) {
            if(data.orderInfo.total_fee >0) {
                return callback(null, data);
            }
            // 添加支付历史纪录
            var hisEnt = new YjxPaymentHisModel({
                trade_type: options.orderType||0,
                trade_obj_id: options.orderId||0,
                trade_obj_no: data.orderInfo.order_no||0,
                state: CONFIG.YJX_ORDER_STATE.PAID,
                pay_platform: 0,// 无
                desc: 'SUCCESS',
                update_by: options.userId||0
            });
            hisEnt.saveToDB(function(insErr, newHisId) {
                if(insErr) {
                    console.log("orderUtil.js [getUnifiedOrderPayParam_WX] Ins PayHis Err: " + insErr);
                }
                orderUtil.updOrderState(options.orderId, options.orderType, CONFIG.YJX_ORDER_STATE.PAID, 0, options.userId, function(updErr2, updRet2){
                    if(updErr2) {
                        return callback(updErr2, null);
                    }
                    // 支付成功后续处理 added by xc 2018-03-27
                    orderUtil.procVipAndPtsOrder({userId:options.userId, orderId:options.orderId, updOdrFlg:1}, function(procErr,procRet){
                        return callback(procErr, procRet);
                    });
                });
            });
        });
        // 5. 识别平台, 分别生成支付参数, 网页
        totalTasks.push(function (data, callback) {
            if(Number(options.device) !== 600) {
                return callback(null, data);
            }
            var param = {uid: options.userId ||0, id: options.orderId||0, type: options.orderType||0};
            var str = yjxAlipayClient.pagePay({
                subject: options.subject || "示界港支付宝支付订单",
                body: options.body || "示界港支付宝支付订单",
                outTradeId: data.orderInfo.order_no,
                timeout: options.timeout || "2h",
                amount: (data.orderInfo.total_fee / 100).toFixed(2),
                goodsType: options.goodsType,
                passbackParams: JSON.stringify(param),
                qrPayMode : 4,
                qrcodeWidth : 230
            });
            data.orderUrl = "https://openapi.alipay.com/gateway.do?"+str;
            return callback(null, data);
        });
        // 6. 识别平台, 分别生成支付参数, app
        totalTasks.push(function (data, callback) {
            if(Number(options.device) !== 610 && Number(options.device) !== 620) {
                return callback(null, data);
            }
            // 苹果支付
            if(Number(options.device) === 620 && data.orderInfo.pay_platform !== 30) {
                return callback('此订单暂不支持 iOS 设备支付', data);
            }
            if(CONFIG.DEBUG) {
                data.orderInfo.total_fee = 1;
            }
            var param = {uid: options.userId ||0, id: options.orderId||0, type: options.orderType||0};
            data.orderStr = yjxAlipayClient.appPay({
                subject: options.subject || "示界港支付宝支付订单",
                body: options.body || "示界港支付宝支付订单",
                outTradeId: data.orderInfo.order_no,
                timeout: options.timeout || "21h",
                amount: (data.orderInfo.total_fee / 100).toFixed(2),
                goodsType: options.goodsType,
                passbackParams: JSON.stringify(param)
            });
            return callback(null, data);
        });
        async.waterfall(totalTasks, function (error, data) {
            if(error) {
                return callback(error, null);
            }
            var ret = {
                orderUrl : data.orderUrl,
                orderStr : data.orderStr
            };
            return callback(null, ret);
        });
    };

    /**
     * 处理只有 userId 异常情况的查询缓存
     * @author 李强
     * @date 2017-11-21
     * @param userId, 用户唯一标识, 可能存在
     * @param orderId, 订单唯一标识, 可能存在
     * @param state, 订单状态, 可能存在
     * @param transactionId IAP 支付唯一标识, 可能存在
     * @param receiptData, IAP 交易凭据, 可能存在
     * @param exceptionType 异常状态标识, 0 标识无异常, 1 标识有异常, 但前端通过缓存已解决, 2, 标识有异常, 前端通过缓存仍无法结局
     * @param callback 回调
     *             error: 是否存储成功
     *
     * */

    orderUtil.reserveErrorState = function(userId, orderId, state, transactionId, receiptData,exceptionType, callback) {
        //特殊处理   将base64位编码的空格替换成加号
        if(receiptData) receiptData = receiptData.replace(/ /g,'+'); // 前置验证逻辑
        // *** 保存异常 log 至数据库 ***
        var insEnt = new YjxPaymentHisModel({
            trade_type: 40,// 订单类型(去水印)
            trade_obj_id: orderId || 0,
            state: state || 0,// 支付成功
            pay_platform: 30,// 苹果内购
            desc: 'app exception IAP log with exceptionType: ' + exceptionType,
            pay_info1: state || '',
            pay_info2: receiptData ||'',
            pay_info6: transactionId ||'',
            update_by: userId || ''
        });
        insEnt.saveToDB(function(saveLogErr, result){
            if(saveLogErr) {
                return callback(saveLogErr, null);
            }
            return callback(null,{});
        });
    };


    /**
     * 更新IAP订单状态
     * @author 李强
     * @date 2017-11-21
     * @param userId, 用户唯一标识, 可能存在
     * @param orderId, 订单唯一标识, 可能存在
     * @param state, 订单状态, 可能存在
     * @param transactionId IAP 支付唯一标识, 可能存在
     * @param receiptData, IAP 交易凭据, 可能存在
     * @param exceptionType 异常状态标识, 0 标识无异常, 1 标识有异常, 但前端通过缓存已解决, 2, 标识有异常, 前端通过缓存仍无法结局
     * @param callback 回调
     *             error: 是否存储成功
     *
     * */
    orderUtil.reserveSuccessState = function(userId, orderId, state, transactionId, receiptData, exceptionType,callback){
        if(receiptData) receiptData = receiptData.replace(/ /g,'+'); // 前置验证逻辑

        // *** 保存异常 log 至数据库 ***
        var insEnt = new YjxPaymentHisModel({
            trade_type: 40,// 订单类型(去水印)
            trade_obj_id: orderId || 0,
            state: state || 0,// 支付成功
            pay_platform: 30,// 苹果内购
            desc: 'app exception IAP log with exceptionType: ' + exceptionType,
            pay_info1: state || '',
            pay_info2: receiptData ||'',
            pay_info6: transactionId ||'',
            update_by: userId || ''
        });
        insEnt.saveToDB(function(saveLogErr, result){
            if(saveLogErr) {
                return callback(saveLogErr, null);
            }

            // 1. 查询订单信息
            var orderModel = new YjxTradeOrderModel({
                order_id : orderId,
                del_flg : 0
            });
            // 更新状态传入: 11 支付成功, 12 支付失败
            // '订单状态:10待支付、11已支付、12支付失败、20制作中、30配送中、40完成、50取消',
            orderModel.findFromDB(function(findOrderErr, orders){
                if(findOrderErr || !orders || orders.length == 0) {
                    return callback(findOrderErr, 12)
                }
                var order = orders[0];
                // 2. 移动端更新状态, 认为支付失败, 无需验证, 直接更新支付失败
                if(state != 11) {
                    // 已完成的订单不处理
                    if(Number(order.state) !== 40) {
                        orderUtil.updOrderState(order.order_id, 40,50,order.total_fee||0,userId,function(updErr, updRet){
                                return callback(updErr, 12); // 取消后返回订单失败
                            }
                        );
                    } else {
                        return callback(findOrderErr, 12);
                    }
                } else {
                    // 3. 如果更新状态为支付成功, 需通过苹果服务器验证是否真的支付成功
                    orderUtil.checkIAPTransactionState(userId, orderId, transactionId, receiptData, function(checkIAPErr, transaction, validateRet){
                        if(checkIAPErr) {
                            return callback(checkIAPErr, null);
                        }

                        // 支付失败
                        if(!transaction || transaction.cancellation_date) {
                            // // 已完成的订单不处理
                            if(Number(order.state) !== 40) {
                                orderUtil.updOrderState(order.order_id, 40, 50, order.total_fee||0, userId, function(updErr, updRet){
                                        return callback(updErr, 12); // 取消后返回订单失败
                                    }
                                );
                            } else {
                                return callback(checkIAPErr, 12); // 取消后返回订单失败
                            }
                        } else {
                            // 支付成功
                            // 添加支付历史纪录
                            var insEnt = new YjxPaymentHisModel({
                                trade_type: 40,// 订单类型
                                trade_obj_id: orderId,
                                trade_obj_no: order.order_no || '',// TODO orderNo
                                state: 11,// 支付成功
                                pay_platform: 30,// 苹果内购
                                desc: 'SUCCESS',
                                pay_info1: 11,
                                pay_info2: receiptData ||'',
                                pay_info3: transaction.product_id||'',
                                pay_info4: transaction.transaction_id||'', //
                                pay_info5: transaction.quantity||'',
                                pay_info6: transaction.original_transaction_id||'',
                                pay_info7: transaction.purchase_date||'',
                                pay_info8: transaction.purchase_date_ms||'',
                                pay_info9: transaction.purchase_date_pst||'',
                                pay_info10: transaction.original_purchase_date||'',
                                pay_info11: transaction.original_purchase_date_ms||'',
                                pay_info12: transaction.original_purchase_date_pst||'',
                                pay_info13: transaction.is_trial_period||'', //
                                pay_info14: validateRet.environment||'',
                                pay_info15: validateRet.receipt_type||0,
                                pay_info16: validateRet.adam_id||'',
                                pay_info17: validateRet.app_item_id||0,
                                pay_info18: validateRet.bundle_id||'',
                                pay_info19: validateRet.application_version||0,
                                pay_info20: validateRet.download_id||0,
                                pay_info21: validateRet.version_external_identifier||'',
                                pay_info22: validateRet.receipt_creation_date||'',
                                pay_info23: validateRet.request_date||'',
                                pay_info24: validateRet.original_purchase_date||'',
                                pay_info25: validateRet.original_application_version ||'',
                                update_by: userId
                            });
                            insEnt.saveToDB(function(insErr, newHisId){
                                if(insErr) {
                                    console.log("orderUtil.js [updateVipOrderState_v6_0] Ins PayHis Err: "+insErr);
                                }
                                // 更新订单为支付成功
                                orderUtil.updOrderState(orderId, 40/*虚拟商品*/, 11/*支付成功*/, order.total_fee, userId, function(updErr, updRet){
                                    //return callback(updErr, 11);

                                    // 支付成功后续处理 added by xc 2018-03-27
                                    orderUtil.procVipAndPtsOrder({userId:userId, orderId:orderId, updOdrFlg:1}, function(procErr,procRet){
                                        return callback(procErr, 11);
                                    });
                                });
                            });
                        }
                    });
                }
            });
        });
    };


    //----------------------------------------------------------------
    /***
     * 通过苹果服务器验证是否真的支付成功
     * @author 李强
     * @date 2017-11-21
     * @param userId 用户唯一标识
     * @param orderId 订单唯一标识
     * @param transactionId 交易唯一标识
     * @param receiptData 验证凭据
     * @param callback 验证回调
     *          error : 验证出错
     *          currentTransaction :  当前交易
     *          result: 验证拿到的所有数据
     * */
    orderUtil.checkIAPTransactionState = function (userId, orderId, transactionId, receiptData, callback) {
        //交易唯一标识不存在,直接返回失败
        if(!transactionId || transactionId.length == 0) {
            return callback(null, 12);
        }

        // 根据receiptData 向苹果服务器验证
        // 1. 验证生产环境
        if(receiptData) receiptData = receiptData.replace(/ /g,'+');

        var param = {
            "receipt-data" : receiptData
        };

        function validateIAP(result) {
            /** IAP 返回状态码
             21000	App Store不能读取你提供的JSON对象
             21002	receipt-data域的数据有问题
             21003	receipt无法通过验证
             21004	提供的shared secret不匹配你账号中的shared secret
             21005	receipt服务器当前不可用
             21006	receipt合法，但是订阅已过期。服务器接收到这个状态码时，receipt数据仍然会解码并一起发送
             21007	receipt是Sandbox receipt，但却发送至生产系统的验证服务
             21008	receipt是生产receipt，但却发送至Sandbox环境的验证服务
             * */
            if(Number(result.status) != 0) {
                console.log("orderUtil.js [checkIAPTransactionState] err: " + result.status);
                return callback("validate IAP transaction err", null);
            }
            // 获取该用户的所有交易信息
            var inApp = result.receipt.in_app;
            if (!inApp || inApp.length ==0) {
                return callback(null, 12); // 没有支付记录, 认定失败
            }

            var  state = 12; // 默认支付失败
            var currentTransaction = null;
            for(var i=0; i < inApp.length; i++) {
                var transaction = inApp[i];

                /** IAP 单笔交易信息字段类型及含义
                 * transaction_id	            integer	交易号
                 * original_transaction_id	    integer	原始交易号
                 * product_id	                string	商品标识符
                 * quantity	                    integer	数量
                 * purchase_date	            string	购买日期
                 * original_purchase_date	    string	原始购买日期
                 * purchase_date_ms	            integer	购买日期(ms)
                 * original_purchase_date_ms	integer	原始购买日期(ms)
                 * purchase_date_pst	        string	购买日期(pst)
                 * original_purchase_date_pst	string	原始购买日期(pst)
                 * cancellation_date	        string	取消购买的日期 (如果存在, 则标识该笔交易被取消)
                 * */
                // 存在该订单, 且该订单没有取消
                if(transaction.transaction_id == transactionId && !transaction.cancellation_date) {
                    currentTransaction = transaction;
                    // todo 此处建议根据 product_id 查询支付的商品价格, 看是否与订单价格相同
                    break;
                }
            }
            return callback(null, currentTransaction, result);

        }
        // 先验证正式环境
        var testIAPServer = "https://sandbox.itunes.apple.com/verifyReceipt"; // 沙盒环境
        var publishIAPServer = "https://buy.itunes.apple.com/verifyReceipt";
        superagent.post(publishIAPServer)
            .send(param)
            .end(function(chkPublishErr, publishRes){
                if(chkPublishErr) {
                    return callback(chkPublishErr, null);
                }
                var result = JSON.parse(publishRes.text);
                // 如果发现沙盒环境的 receipt 被发送到了正式验证, 则切换到沙盒验证接口验证
                if(Number(result.status) == 21007) {
                    console.log("=== 正式环境验证了沙盒环境的交易, 切换回沙盒环境验证 ===");
                    superagent.post(testIAPServer)
                        .send(param)
                        .end(function(chkSandBoxErr, sandboxRes){
                            if(chkSandBoxErr) {
                                return callback(chkSandBoxErr, null);
                            }
                            return validateIAP(JSON.parse(sandboxRes.text));
                        });
                    return;
                }
                return validateIAP(result);
            });
    };

    /**
     * 获取用户订单详情
     *
     * @author 毛凯
     * @date 2017-11-18
     *
     * @param userId	是 299188 用户唯一标识
     * @param orderId	是 879   订单唯一标识
     * @param callback 回调
     *              err 错误信息
     *              result 返回结果
     **/
    orderUtil.getUserOrderDetail_v1_0 = function(userId,orderId,callback){
        (new YjxTradeOrderModel()).getAllOrderList(userId,orderId,function(getListErr,result){
            if(getListErr){
                console.log('userUtil.js [getUserOrderDetail_v1_0] getAllOrderList Err '+getListErr);
                return callback(getListErr,null);
            }
            if(!result){
                return callback(getListErr,null);
            }
            var tasks = [];
            for(var i=0; i<result.length; i++ ) {
                var t = (function(order){
                    //  2[去水印订单],4[秒杀订单],8[vip订单],16[待定]
                    var tag = Number(order.odr_dtl_type_tag);
                    var orderId = order.id;
                    var isWm = tag & 2;
                    if(isWm) {
                        return function(callback) {
                            //3.通过orderId去查询去水印的订单子表
                            (new YjxTradeOrderModel()).getUserWMOrderSubOrderList(orderId,function (getWMOrderErr, getWMOrderRes) {
                                return callback(getWMOrderErr, getWMOrderRes);
                            });
                        }
                    }
                    var isSekil = tag & 4;
                    if(isSekil) {
                        return function(callback){
                            //4.通过orderId去查询秒杀订单子表
                            (new YjxTradeOrderModel()).getUserSKOrderSubOrderList(orderId,function (getSKOrderErr, getSKOrderRes) {
                                return callback(getSKOrderErr, getSKOrderRes);
                            });
                        }
                    }
                    var isVip = tag & 8;
                    if(isVip) {
                        return function(callback){
                            //5.通过orderId去查询vip订单子表
                            (new YjxTradeOrderModel()).getUserVIPOrderSubOrderList(orderId,function (getVIPOrderErr, getVIPOrderRes) {
                                return callback(getVIPOrderErr, getVIPOrderRes)
                            });
                        }
                    }
                    var isPts = tag & 16;
                    if(isPts) {
                        return function(callback){
                            //5.通过orderId去查询充值订单子表
                            (new YjxTradeOrderModel()).getUserPtsOrderSubOrderList(orderId,function (getPtsOrderErr, getPtsOrderRes) {
                                return callback(getPtsOrderErr, getPtsOrderRes)
                            });
                        }
                    }

                })(result[i]);
                if(tasks)tasks.push(t);
            }
            async.parallelLimit(tasks, 5, function(error, tasksResults){
                if(error){
                    return  callback(error,null);
                }
                var retData = {
                    orderInfo : result[0]
                };
                for(var i=0;i<tasksResults.length;++i){
                    var order = result[i];
                    order.detailItems = tasksResults[i];
                }
                return callback(null,retData);
            });
        });
    };


    /*
     * 获取预结算去水印订单信息
     * @author 李强
     * @date 2017-11-21
     * @param device: 6 字段为 一键秀 相关标记
     *             600 一键秀网页端
     *             610 一键秀 android 端
     *             620 一键秀 iOS 端
     *             630 一键秀 嵌入网页端
     *             640 一键秀微信端
     *             650 一键秀小程序端
     * @param userId: 用户唯一标识
     * @param docId:  用户作品唯一标识
     * @param orderType:  订单类型标记去水印订单
     *返回值 : http://114.55.172.253:7000/mock/11/yjx/v1/order/getPreWatermarkOrderInfo_v1_0
     * 测试接口: http://test.itbour.com:3000/yjx/v1/order/getPreWatermarkOrderInfo_v1_0?userId=299188&docId=1&device=610&orderType=2
     */
    orderUtil.getPreWatermarkOrderInfo_v1_0 = function(userId,uniDocId,orderType,callback){
        //通过统一作品id,查询对应的子表的作品id
        var docEntity = new YjxUniUserDocModel();
        docEntity.checkUniUserDocType(uniDocId, function (err, docInfo) {
            if(err) {
                return callback(err, null);
            }
            var docType = Number(docInfo.doc_type); // 作品类型
            var docId = Number(docInfo.doc_id);     // 作品子表唯一标识
            if(!docInfo.watermark){
               return callback("该作品已去水印", null);
            }
            if(docInfo.wm_paid){
               return callback("该作品已支付", null);
            }
            if (Number(docInfo.user_id) !== Number(userId)) {
                return callback('非本账户作品, 无法生成订单', null);
            }
            // 设计
            if(docType == 10) {
                orderUtil.getDesignIdfromDocId(docId,docType,function(err,item){
                    if(err){
                        return callback(err,null);
                    }
                    orderUtil.getPayInfoFromDesign(item.designId,orderType,function(dErr,dresult){
                        //数据整合
                        if(dErr){
                            return callback(dErr,null);
                        }
                        if(!dresult || dresult.length == 0){
                            return callback("暂未找到对应的模版价格",null);
                        }
                        var result = dresult[0];
                        result.opType = 1;
                        result.docId = uniDocId;
                        return callback(dErr,result);
                    })
                })
            }
            // 视频
            else  if(docType == 30) {
                orderUtil.getDesignIdfromDocId(docId,docType,function(err,item){
                    orderUtil.getPayInfoFromVideo(item.designId,orderType,function(dErr,dresult){
                        //数据整合
                        if(dErr){
                            return callback(dErr,null);
                        }
                        if(!dresult || dresult.length == 0){
                            return callback("暂未找到对应的模版价格",null);
                        }
                        var result = dresult[0];
                        result.opType = 2;
                        result.docId = uniDocId;
                        return callback(dErr,result);
                    })
                })
            }
            // ppt
            else if(docType === 20) {
                return callback("ppt作品暂无去水印服务", null);
            }
        });
    };

    /*
     * 通过作品id获取去水印的模版id
     * @author 李强
     * @date 2017-11-21
     * @param docId:  用户子作品唯一标识
     * @param oopType: 设计 10  或者   视频  30类型
     *返回值 : designId
     */
    orderUtil.getDesignIdfromDocId = function(docId,opType,callback){
        if(opType == 10){
            var entity = new YjxDesignUserDocModel({
                "doc_id":docId,
                "del_flg":0
            });
        }else {
            var entity = new YjxVideoUserDocModel({
                "doc_id": docId,
                "del_flg": 0
            });
        }
            entity.findFromDB(function (err, items) {
                if(err){
                    return callback(err,{});
                }
                return callback(null,{designId:items[0].design_id});
            });
        };


    /*
     * 根据子模版id获取对应的商品信息以及商品价格(设计)
     * @author 李强
     * @date 2017-11-21
     * @param designId:  子模版唯一标识
     *返回值 : {}
     */
    orderUtil.getPayInfoFromDesign = function(designId,orderType,callback){
        var entity = new YjxPriceModel();
        entity.getPayInfoFromDesign(designId,orderType,function(deErr,deRes){
            return callback(deErr,deRes)
        })
    };


    /*
     * 根据子模版id获取对应的商品信息以及商品价格(视频)
     * @author 李强
     * @date 2017-11-21
     * @param designId:  子模版唯一标识
     *返回值 : {}
     */
    orderUtil.getPayInfoFromVideo = function(designId,orderType,callback){
        var entity = new YjxPriceModel();
        entity.getPayInfoFromVideo(designId,orderType,function(deErr,deRes){
            return callback(deErr,deRes)
        })
    };


    /**
     * 创建去水印订单
     *
     * @author 毛凯
     * @date 2017-11-18
     *
     * @param device	是 610  6 字段为 一键秀 相关标记
     *                  600 一键秀网页端
     *                  610 一键秀 android 端
     *                  620 一键秀 iOS 端
     *                  630 一键秀 嵌入网页端
     *                  640 一键秀微信端
     *                  650 一键秀小程序端
     * @param userId	是 299188 用户唯一标识
     * @param docId	    是 989 需要去水印的作品id
     * @param payType  是   1固定传 现金支付 2 积分支付
     * @param orderType 是 2 固定传 2, 标记去水印订单
     * @param callback 回调
     *              err 错误信息
     *              result 返回结果
     *
     * 注：orderType固定传 2, 标记去水印订单
     **/
    orderUtil.createWatermarkOrder_v1_0 = function(device,userId,docId,orderType,payType,paymentPlatform,callback){
        (new YjxTradeOrderModel()).updateUserOdrWmBefore(userId,docId,function(err,res){
            if(err) {
                return callback("order.js orderUtil.js [updateUserOdrWmBefore]  err:"+err, null);
            }
            orderUtil.getPreWatermarkOrderInfo_v1_0(userId,docId,orderType,function(err,result) {
                //保存进订单总表
                if(err){
                    console.log("orderUtil.js [getPreWatermarkOrderInfo_v1_0] getPreWatermarkOrderInfoErr " + err);
                    return callback(err,null);
                }
                if(!result){
                    var data = {
                        info : "您还没有水印订单！"
                    };
                    return callback(null,data);
                }

                /*YjxTradeOrderModel表字段
                 state    //TODO 状态
                 inv_id   //TODO  发票id
                 partner_id //TODO 合作平台
                 coupon_fee //TODO 优惠费
                 coupon_id  //TODO 优惠券Id
                 */
                var orderNo=orderUtil.createOrderNo(device,orderType);
                var entity = new YjxTradeOrderModel({
                    order_no: orderNo,
                    pay_order_no: orderNo,
                    detail_cnt: result.qty,
                    device: device,
                    state: 10,
                    inv_id: null,
                    pay_type: payType,
                    pay_platform: paymentPlatform,
                    user_id: userId,
                    odr_dtl_type_tag: 2, //子订单类型标记位(多子订单时按位与,即累加,同类型不重复累加): 2[去水印订单],4[秒杀订单],8[vip订单],16[待定]
                    odr_type: 0, //订单类型: 0常规, 20:原始秒杀订单
                    desc: result.show_name,
                    update_by: userId
                });
                if(payType == 1) {
                    entity.total_fee= result.unit_price;
                }
                if(payType == 2) {
                    entity.total_cost_pts =result.unit_pts;
                }
                //保存到订单总表
                entity.saveToDB(function(orderErr,insertId){
                    if(orderErr){
                        console.log("YjxTradeOrderModel [saveToDB]  orderErr" + orderErr);
                        return callback(err,null);
                    }
                    //保存到水印订单子表
                    //YjxTradeOdrDtlWmModel数据表字段
                    // state //TODO 状态待定
                    var entitySub = new YjxTradeOdrDtlWmModel({
                        detail_no : orderNo,
                        order_id : insertId,
                        price_id : result.price_id,
                        unit : result.unit,
                        qty : result.qty,
                        pay_type : payType,
                        uni_doc_id : result.docId,
                        desc : result.show_name,
                        update_by : userId
                    });
                    if(payType == 1) {
                        entitySub.fee= result.unit_price;
                    }
                    if(payType == 2) {
                        entitySub.cost_pts =result.unit_pts;
                    }
                    entitySub.saveToDB(function(orderSubErr,insertSubId){
                        if(orderSubErr){
                            console.log("YjxTradeOdrDtlWmModel [saveToDB]  orderSubErr" + orderSubErr);
                            return callback(err,null);
                        }
                        var data ={
                            orderId : insertId,
                            orderNo : orderNo,
                            payType : payType
                        };
                        return callback(err,data);
                    });
                });
            });
        });
    };

    /**
     * 获取 vip 商品预支付订单信息_WEB_1_1
     *
     * 参数 vipItemId:    vip 商品唯一标识
     * 参数 priceId:      商品套餐唯一标识
     * 参数 userId:       用户唯一标识
     * 参数 referralCode: 推荐码, 默认为空, 注意: 若推荐码非法则获取预支付信息失败
     * 参数 payType:      1只能用钱支付，2只能用积分支付，3[1+2]两种支付方式均可
     *                   默认与 priceId 对应的套餐所支持的方式为准, 若 套餐支持多种方式则以该参数为准,
     *                   若 payType 指定的支付方式 套餐不支持,返回失败
     * 返回值:
     *     "data" : {
     *        "payType" : 1,              // 1只能用钱支付，2只能用积分支付，3[1+2]两种支付方式均可
     *        // payType 为1 时使用现金数据
     *        "totalFee" : 2998,          // 商品总价格, 浮点型, 保留小数点后两位, 单位: 元
     *        "totalReducePrice" : -200,  // 商品总优惠价格, 浮点型, 保留小数点后两位, 单位: 元
     *        "actualFee" : 2798,         // 实际需支付价格
     *        // payType 为2 时使用积分支付信息
     *        "totalPts" : 0,             // 商品总积分价格, 浮点型, 保留小数点后两位, 单位: 积分(秀米)
     *        "totalReducePts" : 0,       // 商品总优惠积分价格, 浮点型, 保留小数点后两位, 单位: 积分(秀米)
     *        "actualPts" : 0,            // 实际需支付积分
     *     }
     */
    orderUtil.getPreVipOrderInfo_web_v1_1 = function(vipItemId, priceId, userId, referralCode, payType, callback) {
        // 获取vip套餐价格信息
        (new YjxPriceModel).getGoodsPriceInfo(vipItemId,priceId,10/*goodsType:10vip*/,payType,function(pErr,pInfo){
            if(pErr) {
                return callback(pErr, null);
            }
            if(pInfo && pInfo.length>0) {
                var priceInfo = pInfo[0];

                var retInfo = {
                    itemName :priceInfo.goods_name,
                    itemDesc :priceInfo.desc,
                    itemThumb:priceInfo.theme_thumb,
                    priceName:priceInfo.show_name,
                    priceDesc:priceInfo.desc,
                    payType: payType,
                    totalFee: Number(priceInfo.unit_price||'0'),
                    totalReducePrice:0,
                    actualFee: Number(priceInfo.unit_price||'0'),
                    totalPts: Number(priceInfo.unit_pts||'0'),
                    totalReducePts: 0,
                    actualPts: Number(priceInfo.unit_pts||'0')
                };

                if(referralCode && referralCode.length>0) {
                    // 检查推荐码(暂定为推荐人手机号)
                    (new ItbUserModel).getOrgUserByMobile(referralCode, 200/*合作机构　*/, function(uErr, uInfo){
                        if(uErr) {
                            return callback(uErr, null);
                        }

                        if(uInfo && uInfo.length>0) {// 合法推荐人
                            // TODO 优惠额暂时写死
                            if(priceId==101) {// 年度vip
                                retInfo.totalReducePrice=20000; 
                            } else if(priceId==103) {
                                retInfo.totalReducePrice=5000;
                            }
                            retInfo.actualFee=retInfo.totalFee-retInfo.totalReducePrice;
                            return callback(null, retInfo);

                        } else {
                            return callback('无效推荐码', null);
                        }
                    });

                } else {
                    return callback(null, retInfo);
                }

            } else {
                return callback('未获取到价格信息', null);
            }
        });
    };

    /**
     * 创建 vip 商品订单_WEB_1_1
     *
     * 参数 id:           vip 商品唯一标识
     * 参数 priceId:      商品套餐唯一标识
     * 参数 userId:       用户唯一标识
     * 参数 referralCode: 推荐码, 默认为空, 注意: 若推荐码非法则获取预支付信息失败
     * 参数 payType:      1只能用钱支付，2只能用积分支付，3[1+2]两种支付方式均可
     *                   默认与 priceId 对应的套餐所支持的方式为准, 若 套餐支持多种方式则以该参数为准,
     *                   若 payType 指定的支付方式 套餐不支持,返回失败
     * 参数 paymentPlatform: 预定订单现金支付的平台 10 微信支付, 20 支付宝支付, 20 苹果内购
     *                      注意: 此参数仅在 商品支持现金支付时有效, 默认为 10 微信支付
     *
     * 返回值: {
     *   "orderId" : 7877,           // 商品订单id
     *   "orderNo" : "QWERTYUUIIO",  // 商品订单号
     *   "payType" : 1,              // 1只能用钱支付，2只能用积分支付，3[1+2]两种支付方式均可
     * }
     */
    orderUtil.createVipOrder_web_v1_1 = function(device, vipItemId, priceId, userId, referralCode, payType, paymentPlatform, callback) {
        // 获取vip套餐价格信息
        (new YjxPriceModel).getGoodsPriceInfo(vipItemId,priceId,10/*goodsType:10VIP*/,null,function(vErr,vInfo){
            if(vErr) {
                return callback(vErr, null);
            }
            if(vInfo && vInfo.length>0) {
                var vipInfo = vInfo[0];

                // 获取附带商品信息(TODO:暂时尝试取两个)
                var tasks = [];
                if(vipInfo.sub_uni_item_id_1) {
                    tasks.push((function (subUniItemId) {
                        return function (asyncCallback) {
                            (new YjxPriceModel).getGoodsPriceInfo(subUniItemId,null,null,null,function(err, itemInfo){
                                if(err) {
                                    return asyncCallback(err, null);
                                }
                                var retItemInfo = null;
                                if(itemInfo && itemInfo.length>0) {
                                    retItemInfo = itemInfo[0];
                                }
                                return asyncCallback(err, retItemInfo);
                            });
                        };
                    })(vipInfo.sub_uni_item_id_1)); // 利用闭包解决动态参数传递问题
                }
                if(vipInfo.sub_uni_item_id_2) {
                    tasks.push((function (subUniItemId) {
                        return function (asyncCallback) {
                            (new YjxPriceModel).getGoodsPriceInfo(subUniItemId,null,null,null,function(err, itemInfo){
                                if(err) {
                                    return asyncCallback(err, null);
                                }
                                var retItemInfo = null;
                                if(itemInfo && itemInfo.length>0) {
                                    retItemInfo = itemInfo[0];
                                }
                                return asyncCallback(err, retItemInfo);
                            });
                        };
                    })(vipInfo.sub_uni_item_id_2)); // 利用闭包解决动态参数传递问题
                }
                async.series(tasks, function(asyncError, asyncRet){
                    if(asyncError){
                        return  callback(asyncError, null);
                    }

                    var odrDtlTypeTag = 8;//vip
                    var odrTotalFee = vipInfo.unit_price||0;
                    var odrTotalPts = vipInfo.unit_pts||0;
                    var arrSubItemInfo = [];// 附带商品信息
                    if(asyncRet && asyncRet.length>0) {
                        for(var i=0;i<asyncRet.length;i++) {
                            var subItemInfo = asyncRet[i];
                            if(subItemInfo && subItemInfo.goods_type==20) {// 充值包
                                odrDtlTypeTag = odrDtlTypeTag|16;// 按位与
                                odrTotalFee += subItemInfo.unit_price||0;
                                odrTotalPts += subItemInfo.unit_pts||0;

                                arrSubItemInfo.push(subItemInfo);
                            }
                        }
                    }

                    // 检查推荐码
                    chkReferralCode(priceId, referralCode, function(chkErr, chkRet){
                        if(chkErr) {
                            return callback(chkErr, null);
                        }

                        // 生成订单号
                        var orderNo=orderUtil.createOrderNo(device,8/*vip*/);

                        // 创建总订单
                        var odrEnt =new YjxTradeOrderModel({
                            order_no : orderNo,
                            pay_order_no : orderNo,
                            detail_cnt : arrSubItemInfo.length+1,
                            device : device,
                            state : 10,
                            inv_id : null,
                            pay_platform : paymentPlatform,
                            pay_type : 1,// 默认现金
                            total_fee : odrTotalFee-chkRet.discountPrice,
                            total_cost_pts : 0,
                            discount_cd: chkRet.discountCd,
                            discount_fee: chkRet.discountPrice,
                            user_id : userId,
                            odr_dtl_type_tag : odrDtlTypeTag,
                            odr_type : 0 , //订单类型: 0常规, 20:原始秒杀订单
                            desc : vipInfo.goods_name,// TODO
                            update_by : userId
                        });
                        if(payType==2) {
                            odrEnt.pay_platform=100;// 示界港
                            odrEnt.pay_type=2;
                            odrEnt.total_fee=0;
                            odrEnt.total_cost_pts=odrTotalPts;
                        }
                        //保存到订单总表
                        odrEnt.saveToDB(function(orderErr,newOdrId){
                            if(orderErr){
                                console.log("YjxTradeOrderModel [saveToDB]  orderErr" + orderErr);
                                return callback(orderErr,null);
                            }

                            // 创建vip子订单
                            var vipEnt = new YjxTradeOdrDtlVipModel({
                                detail_no : orderNo+'_0',
                                order_id : newOdrId,
                                uni_item_id: vipInfo.uni_item_id,
                                price_id: vipInfo.price_id,
                                unit : '套',// TODO
                                qty : 1,// TODO
                                pay_type : odrEnt.pay_type,
                                fee : (odrEnt.pay_type==2)?0:vipInfo.unit_price,
                                cost_pts: (odrEnt.pay_type==1)?0:vipInfo.unit_pts,
                                state: 0,// TODO
                                desc : vipInfo.goods_name,
                                update_by : userId
                            });
                            vipEnt.saveToDB(function(vipDtlErr,vipDtlId){
                                if(vipDtlErr){
                                    console.log("YjxTradeOdrDtlVipModel [saveToDB]  vipDtlErr" + vipDtlErr);
                                    return callback(vipDtlErr,null);
                                }

                                // 创建附带商品子订单
                                var tasks2 = [];
                                for(var n=0; n<arrSubItemInfo.length; n++) {
                                    tasks2.push((function(idx,subItemInfo) {
                                        return function (asyncCallback) {
                                            var ptsEnt = new YjxTradeOdrDtlPtsModel({
                                                detail_no : orderNo+Number(idx+1),
                                                order_id : newOdrId,
                                                uni_item_id: subItemInfo.uni_item_id,
                                                price_id: subItemInfo.price_id,
                                                unit : '套',// TODO
                                                qty : 1,// TODO
                                                fee: subItemInfo.unit_price,
                                                add_pts: subItemInfo.qty,
                                                state: 0,// TODO
                                                desc : subItemInfo.goods_name,
                                                update_by : userId
                                            });
                                            ptsEnt.saveToDB(function(subDtlErr, subDtlId){
                                                if(subDtlErr){
                                                    console.log("YjxTradeOdrDtlPtsModel [saveToDB]  subDtlErr" + subDtlErr);
                                                    return asyncCallback(subDtlErr,null);
                                                }
                                                return asyncCallback(null, subDtlId);
                                            });
                                        };
                                    })(n,arrSubItemInfo[n])); // 利用闭包解决动态参数传递问题
                                }
                                async.series(tasks2, function(asyncError2, asyncRet2) {
                                    if (asyncError2) {
                                        return callback(asyncError2, null);
                                    }
                                    // 返回
                                    return callback(null, {orderId: newOdrId, orderNo:orderNo, payType:odrEnt.pay_type})
                                });
                            });
                        });
                    });
                });

            } else {
                return callback('未获取到VIP价格信息', null);
            }
        });

        // 检查推荐码
        function chkReferralCode(priceId, code, subCallback) {
            var retData = {
                discountCd: null,
                discountPrice: 0
            };

            if(code && code.length>0) {
                // 检查推荐码(暂定为推荐人手机号)
                (new ItbUserModel).getOrgUserByMobile(code, 200/*合作机构　*/, function(uErr, uInfo){
                    if(uErr) {
                        return subCallback(uErr, null);
                    }

                    if(uInfo && uInfo.length>0) {// 合法推荐人
                        // TODO 优惠额暂时写死
                        if(priceId==101) {// 年度vip
                            retData.discountCd=code;
                            retData.discountPrice=20000;// 单位rmb分
                        } else if(priceId==103) {
                            retData.discountCd=code;
                            retData.discountPrice=5000;// 单位rmb分
                        }
                        return subCallback(null, retData);

                    } else {
                        return subCallback('无效推荐码', null);
                    }
                });

            } else {
                return subCallback(null, retData);
            }
        }
    };

    /**
     * 使用积分支付订单_WEB_1_1
     * @author xc
     * 参数 userId:  用户唯一标识
     * 参数 orderId: 订单唯一标识
     */
    orderUtil.payOrderByPoints_web_v1_1=function(device, userId, orderId, callback){
        // 检查总订单
        var odrEnt = new YjxTradeOrderModel({
            user_id: userId,
            order_id: orderId,
            del_flg:0
        });
        odrEnt.findFromDB(function(odrErr, odrRet){
            if(odrErr) {
                return callback(odrErr, null);
            }

            if(odrRet && odrRet.length>0) {
                var odrInfo = odrRet[0];

                if(Number(odrInfo.pay_type||'0')==1) {
                    return callback('该订单仅支持现金支付', null);
                }

                // 检索子订单
                odrEnt.getOdrDtlBalPtsInfo(orderId, function(dtlErr, dtlRet){
                    if(dtlErr) {
                        return callback(dtlErr, null);
                    }

                    if(dtlRet && dtlRet.length>0) {
                        var tasks = [];
                        var totalCostPts = 0;
                        for(var n=0; n<dtlRet.length; n++) {
                            var tmpDtlInfo = dtlRet[n];
                            // 根据子订单插入积分历史纪录
                            tasks.push((function(idx,dtlInfo) {
                                return function (asyncCallback) {
                                    (new YjxUserPointsHisModel).procInsUserPtsHis(userId
                                        ,dtlInfo.bal_flg, dtlInfo.bal_pts, orderId
                                        ,dtlInfo.odr_dtl_type, dtlInfo.detail_id, dtlInfo.desc
                                        ,function(procErr, procRetCd){
                                            if(procErr) {
                                                return asyncCallback(procErr, null);
                                            }
                                            if(procRetCd==1) {
                                                return asyncCallback('参数错误', null);
                                            } else if(procRetCd==2) {
                                                return asyncCallback('秀米不足', null);
                                            } else if(procRetCd==9) {
                                                return asyncCallback('处理错误', null);
                                            }

                                            return asyncCallback(null, null);
                                        }
                                    );
                                };
                            })(n,tmpDtlInfo)); // 利用闭包解决动态参数传递问题

                            if(tmpDtlInfo && tmpDtlInfo.bal_flg==2) {
                                totalCostPts += tmpDtlInfo.bal_pts;
                            }
                        }

                        // 用于检查支付积分额
                        if(totalCostPts==odrInfo.total_cost_pts) {
                            async.series(tasks, function(asyncErr, asyncRet) {
                                if(asyncErr) {
                                    return callback(asyncErr, null);
                                }

                                // 更新订单状态
                                orderUtil.updOrderState(orderId, 40/*TODO暂定40*/, CONFIG.YJX_ORDER_STATE.PAID, 0, userId, function(updErr, updRet){
                                    if(updErr) {
                                        return callback(updErr, null);
                                    }

                                    return  callback(null, null);
                                }, totalCostPts);
                            });

                        } else {
                            return callback('支付金额不匹配', null);
                        }

                    } else {
                        return callback('未检索到子订单', null);
                    }
                });

            } else {
                return callback('未检索到订单', null);
            }
        });
    };

    //--------------------------------------------------------------------------------------------
    /**
     * 根据vip订单更新vip会员信息
     * @author xc
     */
    orderUtil.updVipExpiryInfo=function(userId, orderId, callback){
        var UNIT_MAP = {
            '年':1, '年度':1,
            '季':2, '季度':2,
            '月':3, '月度':3,
            '周':4, '星期':4,
            '天':5, '日':5
        };
        // 查找vip订单信息
        (new YjxTradeOrderModel).getVipOdrDtlList(userId, orderId, function(getErr, getRet){
            if(getErr){
                return callback(getErr, null);
            }

            if(getRet && getRet.length>0) {
                var vipInfo = getRet[0];// TODO 暂定默认只有一个vip子订单

                var qty = Number(vipInfo.p_qty||'0')*Number(vipInfo.qty||'0');// 服务数＊套餐数
                var unit = UNIT_MAP[vipInfo.p_unit]||3;// 默认单位:月

                // 查找会员信息
                var mbEnt = new YjxMemberModel;
                mbEnt.findVipMember(userId, function(findErr, memberInfo) {
                    if(findErr) {
                        return callback(findErr, null);
                    }

                    mbEnt.getTimeFromDB(function(getErr, dbTime){
                        // 新的有效期开始时间
                        var stTime = dbTime.str_sysdate;// 默认重新计算有效期

                        if(memberInfo) {// 已存在会员信息
                            if(memberInfo.validFlg==1) {
                                // 有效期内: 延长有效期
                                stTime = memberInfo.str_expiry_time;
                            }
                        }
                        // 更新vip订单商品有效期
                        (new YjxTradeOdrDtlVipModel).updVipOdrExpTime(vipInfo.detail_id, userId, stTime, unit, qty, function(updErr){
                            if(updErr){
                                return callback(updErr, null);
                            }

                            if(memberInfo) {
                                // 更新会员信息
                                var resetFlg=(memberInfo.validFlg==1) ? 0 : 1;
                                mbEnt.updVipMemberExpTime(userId, memberInfo.member_id, unit, qty, resetFlg, null,
                                    function(updErr2){
                                        return callback(updErr2, null);
                                    });

                            } else {
                                // 新建会员信息
                                mbEnt.createVipMember(userId, stTime, unit, qty,
                                    function(crtErr, newMbId){
                                        return callback(crtErr, null);
                                    });
                            }
                        });
                    });
                });

            } else {
                //return callback('未找到订单', null);// TODO
                return callback(null, null);
            }
        });
    };

    /**
     * 根据订单计算用户积分信息
     * 涉及积分变化的子订单: 添加用户积分历史纪录
     * @author xc
     */
    orderUtil.updUserPtsHisInfo = function(userId, orderId, callback){
        // 检索子订单
        (new YjxTradeOrderModel).getOdrDtlBalPtsInfo(orderId, function(dtlErr, dtlRet){
            if(dtlErr) {
                return callback(dtlErr, null);
            }

            if(dtlRet && dtlRet.length>0) {
                var tasks = [];
                var totalCostPts = 0;
                for(var n=0; n<dtlRet.length; n++) {
                    var tmpDtlInfo = dtlRet[n];

                    // 根据子订单插入积分历史纪录(充值订单以及消耗积分的订单)
                    if(tmpDtlInfo.odr_dtl_type==16 || (tmpDtlInfo.pay_type & 2)) {
                        tasks.push((function(idx,dtlInfo) {
                            return function (asyncCallback) {

                                (new YjxUserPointsHisModel).procInsUserPtsHis(userId
                                    ,dtlInfo.bal_flg, dtlInfo.bal_pts, orderId
                                    ,dtlInfo.odr_dtl_type, dtlInfo.detail_id, dtlInfo.desc
                                    ,function(procErr, procRetCd){
                                        if(procErr) {
                                            return asyncCallback(procErr, null);
                                        }

                                        if(procRetCd==1) {
                                            return asyncCallback('参数错误', null);
                                        } else if(procRetCd==2) {
                                            return asyncCallback('秀米不足', null);
                                        }

                                        return asyncCallback(null, null);
                                    }
                                );
                            };
                        })(n,tmpDtlInfo)); // 利用闭包解决动态参数传递问题

                        if(tmpDtlInfo && tmpDtlInfo.bal_flg==2/*消耗积分*/) {
                            totalCostPts += tmpDtlInfo.bal_pts;
                        }
                    }
                }

                // 用于检查支付积分额
                //if(totalCostPts==odrInfo.total_cost_pts) {
                    async.series(tasks, function(asyncErr, asyncRet) {
                        if(asyncErr) {
                            return callback(asyncErr, null);
                        }

                        return  callback(null, null);
                    });

                //} else {
                //    return callback('支付金额不匹配', null);
                //}

            } else {
                //return callback('未检索到子订单', null);// TODO
                return callback(null, null);
            }
        });
    };

    /**
     * 根据订单号处理vip和充值订单(注:去水印订单不处理,只处理[已支付]状态订单)
     * vip子订单: 更新用户vip期限
     * 涉及积分变化的子订单: 添加用户积分历史纪录
     * @author xc
     * @param options
     * @param options.userId: 用户id
     * @param options.orderId: 订单id
     * @param options.updOdrFlg: 0不更新订单状态, 1更新订单状态
     * @param callback
     */
    orderUtil.procVipAndPtsOrder = function(options, callback){
        // 检查总订单
        var odrEnt = new YjxTradeOrderModel({
            user_id: options.userId,
            order_id: options.orderId,
            del_flg:0
        });
        odrEnt.findFromDB(function(findErr, findRet) {
            if(findErr) {
                return callback(findErr, null);
            }

            if(findRet && findRet.length>0) {
                var odrInfo = findRet[0];

                if( (odrInfo.state != 11) // 只处理［已支付］状态订单
                    || (odrInfo.odr_dtl_type_tag & 2) // TODO 不处理去水印订单
                ) {
                    return callback(null, null);
                }

                // 处理vip子订单
                orderUtil.updVipExpiryInfo(options.userId, options.orderId, function(procErr, procRet){
                    if(procErr) {
                        return callback(procErr, null);
                    }

                    // 处理积分相关子订单
                    orderUtil.updUserPtsHisInfo(options.userId, options.orderId, function(procErr2, procRet2){
                        if(procErr2) {
                            return callback(procErr2, null);
                        }

                        if(options.updOdrFlg) {
                            // 更新订单状态为完成 TODO
                            // 更新订单状态
                            orderUtil.updOrderState(options.orderId, 40, CONFIG.YJX_ORDER_STATE.FINISH, 0, options.userId, function(updErr, updRet){
                                if(updErr) {
                                    return callback(updErr, null);
                                }

                                return  callback(null, null);
                            });

                        } else {
                            return callback(null, null);
                        }
                    });
                });

            } else {
                return callback('未知订单', null);
            }
        });
    };

    /*
     * 获取 vip 商品列表_WEB_1_1 添加
     * @author 毛凯
     * @date 2018-3-24
     */
    orderUtil.getVipGoodsInfo_web_v1_1 = function(callback){
        var entity = new YjxUniItemsModel();
        entity.getUniItemVipInfo(function(deErr,deRes){
            if(deErr){
                return callback(deErr,null);
            }
            if(!deRes ||deRes.length<=0 ){
                return callback("没有获取到vip商品",null);
            }
            var vipGoods= {};
            for(var i = 0;i<deRes.length;i++){
                var goods= deRes[i];
                if(!vipGoods[goods.uni_item_id]){
                    vipGoods[goods.uni_item_id]={
                        id : goods.uni_item_id,
                        order : goods.order,
                        itemName : goods.itemName,
                        itemDesc : goods.itemDesc,
                        priceInfo:[]
                    };
                }
                vipGoods[goods.uni_item_id].priceInfo.push(goods)
            }
            var data = {};
            data.list=[];
            for(var key in vipGoods){
                data.list.push(vipGoods[key]);
            }
            data.list.sort(function(a, b){
                return a.order - b.order;
            });

            return callback(null,data);
        })
    };


    /*
     * 获取 充值 商品列表_WEB_1_1 添加
     * @author 毛凯
     * @date 2018-3-24
     */
    orderUtil.getRechargeXMItems_app_v1_6 = function(callback){
        var entity = new YjxUniItemsModel();
        entity.getRechargeInfo(function(deErr,deRes){
            if(deErr){
                return callback(deErr,null);
            }
            if(!deRes ||deRes.length<=0 ){
                return callback("没有获取到充值商品信息",null);
            }
            var Recharges= {};
            for(var i = 0;i<deRes.length;i++){
                var Recharge = deRes[i];
                if(!Recharges[Recharge.uni_item_id]){
                    Recharges[Recharge.uni_item_id]={
                        id : Recharge.uni_item_id,
                        order : Recharge.order,
                        itemName : Recharge.itemName,
                        itemDesc : Recharge.itemDesc,
                        priceInfo:[]
                    };
                }
                Recharges[Recharge.uni_item_id].priceInfo.push(Recharge)
            }
            var data = {};
            data.list=[];
            for(var key in Recharges){
                data.list.push(Recharges[key]);
            }
            data.list.sort(function(a, b){
                return a.order - b.order;
            });

            return callback(null,data);
        })
    };

    /**
     * 获取 vip 商品预支付订单信息_WEB_1_1
     *
     * @author 毛凯
     * @param vipItemId:    vip 商品唯一标识
     * @param priceId:      商品套餐唯一标识
     * @param userId:       用户唯一标识
     * @param referralCode: 推荐码, 默认为空, 注意: 若推荐码非法则获取预支付信息失败
     * 返回值:
     *     "data" : {
     *        "payType" : 1,              // 1只能用钱支付，2只能用积分支付，3[1+2]两种支付方式均可
     *        // payType 为1 时使用现金数据
     *        "totalFee" : 2998,          // 商品总价格, 浮点型, 保留小数点后两位, 单位: 元
     *        "totalReducePrice" : -200,  // 商品总优惠价格, 浮点型, 保留小数点后两位, 单位: 元
     *        "actualFee" : 2798,         // 实际需支付价格
     *        // payType 为2 时使用积分支付信息
     *        "totalPts" : 0,             // 商品总积分价格, 浮点型, 保留小数点后两位, 单位: 积分(秀米)
     *        "totalReducePts" : 0,       // 商品总优惠积分价格, 浮点型, 保留小数点后两位, 单位: 积分(秀米)
     *        "actualPts" : 0,            // 实际需支付积分
     *     }
     */
    orderUtil.getPreRechargeOrderInfo_app_v1_6 = function(ItemId, priceId, userId, referralCode,callback) {
        // 获取充值套餐价格信息
        (new YjxPriceModel).getGoodsPriceInfo(ItemId,priceId,20/*goodsType:20充值包*/,1,function(pErr,pInfo){
            if(pErr) {
                return callback(pErr, null);
            }
            if(pInfo && pInfo.length>0) {
                var priceInfo = pInfo[0];

                var retInfo = {
                    id: ItemId,
                    itemName :priceInfo.goods_name,
                    itemDesc :priceInfo.desc,
                    displayThumb:priceInfo.theme_thumb ||"",
                    fee: Number(priceInfo.unit_price ||'0'),
                    pts: Number(priceInfo.qty ||'0'),
                };

                if(referralCode && referralCode.length>0) {
                    // 检查推荐码(暂定为推荐人手机号)
                    (new ItbUserModel).getOrgUserByMobile(referralCode, 200/*合作机构　*/, function(uErr, uInfo){
                        if(uErr) {
                            return callback(uErr, null);
                        }

                        if(uInfo && uInfo.length>0) {// 合法推荐人
                            // TODO 优惠额暂时写死
                            if(priceId==101) {// 年度vip
                                retInfo.totalReducePrice=20000;
                            } else if(priceId==103) {
                                retInfo.totalReducePrice=5000;
                            }
                            retInfo.actualFee=retInfo.totalFee-retInfo.totalReducePrice;
                            return callback(null, retInfo);

                        } else {
                            return callback('无效推荐码', null);
                        }
                    });

                } else {
                    return callback(null, retInfo);
                }

            } else {
                return callback('未获取到价格信息', null);
            }
        });
    };

    /**
     * 创建 vip 商品订单_WEB_1_1
     * 参数 device :    设备标识
     * 参数 ItemId:       商品唯一标识
     * 参数 priceId:      商品套餐唯一标识
     * 参数 userId:       用户唯一标识
     * 参数 referralCode: 推荐码, 默认为空, 注意: 若推荐码非法则获取预支付信息失败
     * 参数 payType:      1只能用钱支付，2只能用积分支付，3[1+2]两种支付方式均可
     *                   默认与 priceId 对应的套餐所支持的方式为准, 若 套餐支持多种方式则以该参数为准,
     *                   若 payType 指定的支付方式 套餐不支持,返回失败
     * 参数 paymentPlatform: 预定订单现金支付的平台 10 微信支付, 20 支付宝支付, 20 苹果内购
     *                      注意: 此参数仅在 商品支持现金支付时有效, 默认为 10 微信支付
     *
     * 返回值: {
     *   "orderId" : 7877,           // 商品订单id
     *   "orderNo" : "QWERTYUUIIO",  // 商品订单号
     *   "payType" : 1,              // 1只能用钱支付，2只能用积分支付，3[1+2]两种支付方式均可
     * }
     */
    orderUtil.createRechargeXMOrder_app_v1_6 = function(device, ItemId, priceId, userId, referralCode, paymentPlatform, callback) {
        // 获取充值包价格信息
        (new YjxPriceModel).getGoodsPriceInfo(ItemId,priceId,20/*goodsType:20充值包*/,1,function(rErr,rInfo){
            if(rErr) {
                return callback(rErr, null);
            }
            if(rInfo && rInfo.length>0) {
                var RechargeInfo = rInfo[0];
                var odrDtlTypeTag = 16;//充值包
                var odrTotalFee = RechargeInfo.unit_price||0;
                var odrTotalPts = RechargeInfo.qty||0;
                // 检查推荐码
                chkReferralCode(priceId, referralCode, function(chkErr, chkRet){
                    if(chkErr) {
                        return callback(chkErr, null);
                    }
                    // 生成订单号
                    var orderNo=orderUtil.createOrderNo(device,16/*充值包*/);

                    // 创建总订单
                    var odrEnt =new YjxTradeOrderModel({
                        order_no : orderNo,
                        pay_order_no : orderNo,
                        detail_cnt : 1,
                        device : device,
                        state : 10,
                        inv_id : null,
                        pay_platform : paymentPlatform,
                        pay_type : 1,// 默认现金
                        total_fee : odrTotalFee,
                        total_cost_pts : 0,
                        discount_cd: referralCode,
                        user_id : userId,
                        odr_dtl_type_tag : odrDtlTypeTag,
                        odr_type : 0 , //订单类型: 0常规, 20:原始秒杀订单
                        desc : RechargeInfo.goods_name,// TODO
                        update_by : userId
                    });
                    //保存到订单总表
                    odrEnt.saveToDB(function(orderErr,newOdrId){
                        if(orderErr){
                            console.log("YjxTradeOrderModel [saveToDB]  orderErr" + orderErr);
                            return callback(orderErr,null);
                        }
                        // 创建附带商品子订单
                        var ptsEnt = new YjxTradeOdrDtlPtsModel({
                            detail_no : orderNo,
                            order_id : newOdrId,
                            uni_item_id: RechargeInfo.uni_item_id,
                            price_id: priceId,
                            unit : '次',// TODO
                            qty : 1,// TODO
                            fee: odrTotalFee,
                            add_pts: odrTotalPts,
                            state: 0,// TODO
                            desc : RechargeInfo.goods_name,
                            update_by : userId
                        });
                        ptsEnt.saveToDB(function(subDtlErr, subDtlId){
                            if(subDtlErr){
                                console.log("YjxTradeOdrDtlPtsModel [saveToDB]  subDtlErr" + subDtlErr);
                                return callback(subDtlErr,null);
                            }
                            // 返回
                            return callback(null, {orderId: newOdrId, orderNo:orderNo, payType:odrEnt.pay_type})
                        });
                    });
                });
            }else {
                return callback('未获取到充值价格信息', null);
            }
        });

        // 检查推荐码
        function chkReferralCode(priceId, code, subCallback) {
            var retData = {
                discountCd: null,
                discountPrice: 0
            };

            if(code && code.length>0) {
                // 检查推荐码(暂定为推荐人手机号)
                (new ItbUserModel).getOrgUserByMobile(code, 200/*合作机构　*/, function(uErr, uInfo){
                    if(uErr) {
                        return subCallback(uErr, null);
                    }

                    if(uInfo && uInfo.length>0) {// 合法推荐人
                        // TODO 优惠额暂时写死
                        if(priceId==101) {// 年度vip
                            retData.discountCd=code;
                            retData.discountPrice=20000;// 单位rmb分
                        } else if(priceId==103) {
                            retData.discountCd=code;
                            retData.discountPrice=5000;// 单位rmb分
                        }
                        return subCallback(null, retData);

                    } else {
                        return subCallback('无效推荐码', null);
                    }
                });

            } else {
                return subCallback(null, retData);
            }
        }
    };





    //-------------------------------------------
    return orderUtil;
})();

module.exports = orderUtil;

